// PGLDataVectorPairs.h: interface for the CPGLDataVectorPairs class.
//
//////////////////////////////////////////////////////////////////////

#if !defined(AFX_PGLDATAVECTORPAIRS_H__DD192044_EB6A_48C6_999D_23E5CB00F26D__INCLUDED_)
#define AFX_PGLDATAVECTORPAIRS_H__DD192044_EB6A_48C6_999D_23E5CB00F26D__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#include <pgl/core/PGLDataVectors.h>

/*!
	\defgroup PGLVectorPairRefGroup Vector of Pairs, based on a reference to vector<pair<,>>.
\ingroup PGLDataGroup
*/

/*! \brief Virtual pair vector template

  A vector of pairs. You choose the first or second argument with bFirst parameter.

  \ingroup PGLVectorPairRefGroup
*/
template <class T1, class T2>
class PGLCORE_EXT_CLASS CPGLVectorPairRef : public CPGLData
{
public:
	//! \name Type defintions
	//@{
	//! Pair of <T1,T2>
	typedef struct std::pair<T1, T2> PairDef;
	//! Vector of pairs
	typedef std::vector<PairDef> VectorPairDef;
	//@}

	//! \name Constructors
	//@{
	//! Default constructor
	CPGLVectorPairRef<T1,T2>(bool bFirst = true):m_pVPairs(NULL), m_bFirst(bFirst){};
	//! Construct from reference to v, v must be valid
	CPGLVectorPairRef<T1,T2>(const VectorPairDef& v, bool bFirst = true) 
		: m_pVPairs(&v), m_bFirst(bFirst){};
	//! Construct from handle pV, pV must be valid
	CPGLVectorPairRef<T1,T2>(const VectorPairDef* pVPairs, bool bFirst = true)
		: m_pVPairs(pVPairs),  m_bFirst(bFirst){};
	//! Copy constructor
	CPGLVectorPairRef<T1,T2>(const CPGLVectorPairRef<T1,T2>& v):m_pVPairs(NULL){	*this = v;};
	//! Assignement constructor
	CPGLVectorPairRef<T1,T2>& operator = (const CPGLVectorPairRef<T1,T2>& v){	if (this != &v) { m_pVPairs = v.m_pVPairs; m_bFirst=v.m_bFirst;} return *this;};
	virtual ~CPGLVectorPairRef<T1,T2>() {};
	//@}

	//! \name Virtual overrides
	//@{
	//! returns the size of the vector
	size_t size() const						{	if (!m_pVPairs) return 0; return m_pVPairs->size();};
	//! member access, cosnt
	float at(size_t i) const		
	{	
		ASSERT(m_pVPairs);
		ASSERT(i<m_pVPairs->size()); 
		if (m_bFirst) 
			return static_cast<float>((*m_pVPairs)[i].first); 
		else
			return static_cast<float>((*m_pVPairs)[i].second);
	};
	//! resize
	void resize(size_t n)					{	if (!m_pVPairs) return; const_cast<VectorPairDef*>(m_pVPairs)->resize(n);};
	//! resize
	void clear()							{	if (!m_pVPairs) return; const_cast<VectorPairDef*>(m_pVPairs)->clear();};
	//@}

	//! \name Vector manipulation
	//@{
	//! Setting the reference
	void SetV(const VectorPairDef& v)	{	m_pVPairs=&v;};
	//! returns the reference vector
	const VectorPairDef& GetVPairs() const	{	return *m_pVPairs;};
	//! returns first vector
	void GetVFirst(std::vector<T1>& v) const
	{
		if (!m_pVPairs)
			return;
	
		v.resize(m_pVPairs->size());
		for (size_t i=0;i<m_pVPairs->size();i++)
			v[i] = m_pVPairs->at(i).first;
	};
	//! returns second vector
	void GetVSecond(std::vector<T2>& v) const
	{
		if (!m_pVPairs)
			return;

		v.resize(m_pVPairs->size());
		for (size_t i=0;i<m_pVPairs->size();++i)
			v[i] = m_pVPairs->at(i).second;
	};
	//@}

	//! \name First and second
	//@{
	//! Sets first of pair
	void SetFirst(bool bTrue = true)	{	m_bFirst = bTrue;};
	//! Sets first of pair
	void SetSecond(bool bTrue = true)	{	m_bFirst = !bTrue;};
	//! return true if first is chosen
	bool IsFirst() const				{	return m_bFirst;};
	//! return true if second is chosen
	bool IsSecond() const				{	return !m_bFirst;};
	//@}

protected:
	//! \name Attributes
	//@{
	//! pointer to vector
	const VectorPairDef* m_pVPairs;
	//! first or second
	bool m_bFirst;
	//@}
};

#ifndef PGL_DECLARE_VECTORPAIRREF_DATA_TYPE
#define PGL_DECLARE_VECTORPAIRREF_DATA_TYPE( className , classTypeFirst, classTypeSecond) \
class PGLCORE_EXT_CLASS className : public CPGLVectorPairRef< classTypeFirst, classTypeSecond > \
{ \
PGL_DECLARE_DATA_TYPE( className, CPGLData, false, true ); \
public: \
	className () {}; \
	className (const VectorPairDef& v, bool bFirst = true) \
	: CPGLVectorPairRef< classTypeFirst, classTypeSecond> (v, bFirst){}; \
	className (const VectorPairDef* pV, bool bFirst = true) \
	: CPGLVectorPairRef< classTypeFirst, classTypeSecond> (pV, bFirst) {}; \
	className (const className & v)					{	*this = v;}; \
	className & operator = (const className & v) \
	{	if (this != &v) { this->CPGLVectorPairRef< classTypeFirst, classTypeSecond >::operator =(v); } return *this;}; \
};\
PGL_DECLARE_SMARTPTR( className )
#endif

/*! \class CPGLVectorPairRefFF
	\brief A reference to a vector of pair<float, float>
	\sa CPGLVectorPairRef
  \ingroup PGLVectorPairRefGroup
*/
PGL_DECLARE_VECTORPAIRREF_DATA_TYPE( CPGLVectorPairRefFF, float, float);

/*! \class CPGLVectorPairRefDI
	\brief A reference to a vector of pair<double,int>
	\sa CPGLVectorPairRef
  \ingroup PGLVectorPairRefGroup
*/
PGL_DECLARE_VECTORPAIRREF_DATA_TYPE( CPGLVectorPairRefDI, double, int);

/*! \class CPGLVectorPairRefDS
	\brief A reference to a vector of pair<double,short>
	\sa CPGLVectorPairRef
  \ingroup PGLVectorPairRefGroup
*/
PGL_DECLARE_VECTORPAIRREF_DATA_TYPE( CPGLVectorPairRefDS, double,short);

/*! \class CPGLVectorPairRefIS
	\brief A reference to a vector of pair<int,short>
	\sa CPGLVectorPairRef
  \ingroup PGLVectorPairRefGroup
*/
PGL_DECLARE_VECTORPAIRREF_DATA_TYPE( CPGLVectorPairRefIS, int, short);

/*! \class CPGLVectorPairRefLL
	\brief A reference to a vector of pair<long,long>
	\sa CPGLVectorPairRef
  \ingroup PGLVectorPairRefGroup
*/
PGL_DECLARE_VECTORPAIRREF_DATA_TYPE( CPGLVectorPairRefLL, long, long);



#endif // !defined(AFX_PGLDATAVECTORPAIRS_H__DD192044_EB6A_48C6_999D_23E5CB00F26D__INCLUDED_)
